package com.dlc.felear.xiaoensale.deviceControlSf;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;

import com.dlc.felear.xiaoensale.constant.Constant;
import com.dlc.felear.xiaoensale.dao.ActionStepItemDao;
import com.dlc.felear.xiaoensale.dao.FlavourSpeedDao;
import com.dlc.felear.xiaoensale.deviceUtil.Serialhelper;
import com.dlc.felear.xiaoensale.dlc_serial_port.DlcSerialPortClient;
import com.dlc.felear.xiaoensale.entity.ActionStepItem;
import com.dlc.felear.xiaoensale.entity.CookingMenu;
import com.dlc.felear.xiaoensale.entity.FlavourSpeed;
import com.dlc.felear.xiaoensale.entity.Operator;
import com.dlc.felear.xiaoensale.factory.CmdList;
import com.dlc.felear.xiaoensale.helper.JsonHelper;
import com.dlc.felear.xiaoensale.helper.Session;
import com.dlc.felear.xiaoensale.utils.PlayVoiceUtil;

import org.apache.commons.lang3.StringEscapeUtils;
import org.simple.eventbus.EventBus;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

public class OperatorAutoHandle implements Handler.Callback {
    private static final String TAG = "OperatorAutoHandle";

    private static OperatorAutoHandle instance;
    public static final int DELAYTIME = 10000;
    private static final int WHAT_PUT = 3423;
    private static final int WHAT_DELAY_LH_C = 3413;
    private static final int WHAT_DELAY_GT = 3425;
    private static final int WHAT_DELAY = 3424;
    private Context context;
    private Handler handler;
    private List<Operator> tempOperaterList;
    private int tatalStep = 0;
    private int currentStep = 0;
    private OperatorAutoHandleCallback callback;
    private NewDeviceControl newDeviceControl;
    private FlavourSpeedDao flavourSpeedDao;
    private ActionStepItemDao actionStepItemDao;
    private boolean isWorking;
    private boolean isCookingPage;
    private int gzdelay = 20;
    private int costTime = 0;
    private CookingMenu currentCookingMenu;


    public void setCookingPage(boolean cookingPage) {
        isCookingPage = cookingPage;
    }

    public void setCallback(OperatorAutoHandleCallback callback) {
        this.callback = callback;
    }

    public static OperatorAutoHandle getInstance(Context context, NewDeviceControl newDeviceControl, String tag) {
        Log.e(TAG, "init context=" + context + " newDeviceControl=" + newDeviceControl + "tag=" + tag);
        if (instance == null) {
            synchronized (OperatorAutoHandle.class) {
                if (instance == null) {
                    instance = new OperatorAutoHandle(context, newDeviceControl);
                }
            }
        }
        return instance;
    }

    public void setCurrentCookingMenu(CookingMenu currentCookingMenu) {
        this.currentCookingMenu = currentCookingMenu;
    }

    private OperatorAutoHandle(Context context, NewDeviceControl newDeviceControl) {
        if (newDeviceControl != null && context != null) {
            handler = new Handler(this);
            this.newDeviceControl = newDeviceControl;
            this.context = context;
            flavourSpeedDao = new FlavourSpeedDao(context);
            actionStepItemDao = new ActionStepItemDao(context);
            newDeviceControl.setOperatorAutoHandle(this);
            gzdelay = 20;
            LiaoheControl.ALL_TIMEOUT = gzdelay * 1000;
        }
    }

    @Override
    public boolean handleMessage(Message msg) {
        if (msg.what == WHAT_PUT) {
            try {
                Operator operator = (Operator) msg.obj;
                if (operator != null) {
                    if (!TextUtils.equals(operator.getName(), Constant.ACTION_NAME_CCDD)) {
                        currentStep++;
                        sendCallbackResult(operator);
                    }
                    showMsg(operator);
                    sendCmd(operator);
                    payTips(operator);
//                    Log.e(TAG, "第" + operator.getNum() + "步：" + operator.getName() + " 时长=" + operator.getDelayTime());
                }

            } catch (Exception e) {
                Log.e(TAG, "handleMessage Exception=" + e.getMessage());
            }
        } else if (msg.what == WHAT_DELAY) {
            delayHandler();
        } else if (msg.what == WHAT_DELAY_GT) {
            handler.sendEmptyMessageDelayed(WHAT_DELAY, 3000);
        }
        return false;
    }


    public void startOperator(List<Operator> list) {
        Log.e(TAG, "step=" + JsonHelper.toJson(list));
        if (list == null || list.isEmpty()) {
            return;
        }
        isWorking = true;
        tatalStep = list.size();
        tempOperaterList = list;
        handler.sendEmptyMessageDelayed(WHAT_DELAY, 3333);
    }


    private void delayHandler() {
        firstStep();
        inputQueue(tempOperaterList);
    }

    private long lastTimestamp;

    public void showMsg(Operator operator) {
        Log.e(TAG, "第" + currentStep + "步：" + JsonHelper.toJson(operator) + " 时间间隔:" + (System.currentTimeMillis() - lastTimestamp));
        lastTimestamp = System.currentTimeMillis();
    }

    private void firstStep() {
        try {
            Log.e(TAG, "firstStep");
            allCloseTiaoliao();
            newDeviceControl.isChaocaiStatus(true);
            currentStep = 0;
            lastTimestamp = System.currentTimeMillis() + 1000;
            //转动翻料盒
            Operator operator = tempOperaterList.get(currentStep);
            sendCmd(operator);
            currentStep = 1;
            showMsg(operator);
            sendCallbackResult(operator);
        } catch (Exception e) {

        }
    }

    public int getCostTime(List<Operator> list) {
        return getOperDuring(addOtherOperator(list));
    }

    private void inputQueue(List<Operator> list) {
        try {
            list = addOtherOperator(list);
            int startIndex = -1;
            int endIndex = -1;
            int size = list.size();
            for (int i = 0; i < size; i++) {
                Operator operator = list.get(i);
                if (TextUtils.equals(operator.getName(), Constant.ACTION_NAME_CCSC)) {
                    startIndex = i + 1;
                }
                if (operator.getType() == Constant.ACTION_STEP_JYT &&
                        !TextUtils.equals(operator.getName(), Constant.ACTION_NAME_YOU) && operator.getNum() > startIndex) {
                    endIndex = i + 1;
                }
            }
            Log.e("qindaji", " endIndex=" + endIndex + " startIndex=" + startIndex);
            costTime = getOperDuring(list);
            Log.e("qindaji", "炒菜总时间:" + (costTime) / 1000 + "秒");
            long baseDelayTime = getHandleDelay(list.get(0));
            for (int i = 1; i < list.size(); i++) {
                Operator operator1 = list.get(i - 1);
                Operator operator = list.get(i);
                Message message = new Message();
                message.what = WHAT_PUT;
                message.obj = operator;
                int tempDelay = 0;
                if (operator1.getType() == Constant.ACTION_STEP_JYT
                        && (operator1.getNum() >= startIndex && operator1.getNum() <= endIndex)) {
                    tempDelay = 1;

                } else {
                    tempDelay = getHandleDelay(operator1);
                }
                baseDelayTime += tempDelay;
                Log.e("qindaji", "第" + operator.getNum() + "步:" + operator.getName() +
                        " 执行时间:" + tempDelay / 1000 + " opertor:" + JsonHelper.toJson(operator));
                handler.sendMessageDelayed(message, baseDelayTime);
            }
        } catch (Exception e) {
            Log.e(TAG, e.getMessage());
        }
    }

    /**
     * 处理位于炒菜时长后的液体调料同时下
     *
     * @param list
     * @return
     */
    private List<Operator> addOtherOperator(List<Operator> list) {
        List<Operator> tempList = new ArrayList<>();
        int startIndex = -1;
        int endIndex = -1;
        int maxsc = 0;
        int size = list.size();
        for (int i = 0; i < size; i++) {
            Operator operator = list.get(i);
            if (i > 1 && i < (size-1)) {
                Operator gz1 = list.get(i - 1);
                Operator gz2 = list.get(i + 1);
                if (gz1 != null && gz2 != null &&TextUtils.equals(operator.getName(), Constant.ACTION_NAME_CCJD)&& TextUtils.equals(gz1.getName(), Constant.ACTION_NAME_JSC)
                        && TextUtils.equals(gz2.getName(), Constant.ACTION_NAME_JSC)) {
                    Log.e(TAG, "addOtherOperator:重置两个格子之间的时间");
                    if (operator.getValue() <= 10) {
                        operator.setValue(10);
                    }
                }
                if(TextUtils.equals(operator.getName(), Constant.ACTION_NAME_JSC)
                        &&TextUtils.equals(gz2.getName(), Constant.ACTION_NAME_JSC)){
                    operator.setDelayTime(1);
                }
            }

            tempList.add(operator);
            if (TextUtils.equals(operator.getName(), Constant.ACTION_NAME_CCSC)) {
                startIndex = i;
            }
            if (operator.getType() == Constant.ACTION_STEP_JYT &&
                    !TextUtils.equals(operator.getName(), Constant.ACTION_NAME_YOU) && operator.getNum() > startIndex) {
                endIndex = i;
                int temp = mlVavluechangeMsec(operator.getName(), operator.getValue1());
                if (temp > maxsc) {
                    maxsc = temp;
                }
                Log.e(TAG, operator.getName() + "换算时长:" + temp + " maxsc=" + maxsc);
            }
        }
        Log.e(TAG, "startIndex=" + startIndex + " endIndex=" + endIndex + " maxsc=" + maxsc);
        if (maxsc > 1000 && endIndex != -1) {
            Operator operator = new Operator();
            operator.setName(Constant.ACTION_NAME_CCDD);
            operator.setDelayTime((int) Math.ceil(maxsc / 1000));
            tempList.add(endIndex + 1, operator);
            Log.e(TAG, "添加等待步骤:" + JsonHelper.toJson(operator));
        }
        for (Operator operator:tempList){
          Log.e(TAG,"addOtherOperator:"+JsonHelper.toJson(operator));
        }
        Log.e(TAG, "size1=" + size + " size2=" + tempList.size() + " 添加等待指令后: " + JsonHelper.toJson(tempList));
        return tempList;
    }


    public void stopAllAction() {
        isWorking = false;
        handler.removeMessages(WHAT_DELAY);
        handler.removeMessages(WHAT_DELAY_GT);
        handler.removeMessages(WHAT_PUT);
        newDeviceControl.allActionStop();
    }

    private void sendCmd(Operator operator) {
        ActionStepItem temp = actionStepItemDao.queryForAllByName(operator.getName());
        if (temp != null) {
            operator.setNum(temp.getSerialNo());
        }
        if (TextUtils.equals(operator.getName(), Constant.ACTION_NAME_CCSC)) {
            operator.setValue1(changeZfVlaue(getPValue("zf")));
        }
        if (TextUtils.equals(operator.getName(), Constant.ACTION_NAME_JSC)) {
            operator.setValue1(changeZfVlaue(getPValue("jr")));
        }

        EventBus.getDefault().post(reInitOperator(operator), Constant.ACTION_CMD_INFO_DEBUG);
    }

    private int changeZfVlaue(String value) {
        int temp = 0;
        try {
            temp = Integer.parseInt(value);
        } catch (Exception e) {

        }
        return temp;
    }


    private Operator reInitOperator(Operator operator) {
        if (operator.getType() == Constant.ACTION_STEP_JYT) {
            operator.setValue(0);
        }
        return operator;
    }

    private int getHandleDelay(Operator operator) {
        int temp = 1;
        switch (operator.getName()) {
            case Constant.ACTION_NAME_YOU:
                temp = 1000;
                Log.e(TAG, "加液体:" + operator.getName() + " value1" + operator.getValue1() + " 换算时间=" + temp);
                break;
            case Constant.ACTION_NAME_LAOCHOU:
            case Constant.ACTION_NAME_HHJY:
            case Constant.ACTION_NAME_HONGYOU:
            case Constant.ACTION_NAME_GQZ:
            case Constant.ACTION_NAME_YTJJ:
            case Constant.ACTION_NAME_SHUI:
            case Constant.ACTION_NAME_SHUI1:
                temp = mlVavluechangeMsec(operator.getName(), operator.getValue1());
                Log.e(TAG, "加液体:" + operator.getName() + " value1" + operator.getValue1() + " 换算时间=" + temp);
                break;
            case Constant.ACTION_NAME_JSC:
                temp = operator.getDelayTime();
                if (temp <=1 ) {
                    temp = 1000;
                } else {
                    temp = gzdelay * 1000;
                }
                Log.e(TAG, "getHandleDelay,格子默认时间:" + temp / 1000);
                break;
            default:
                temp = operator.getDelayTime() * 1000;
        }
        if (temp < 1000) {
            Log.e(TAG, "getHandleDelay: 重置确保最小值是：1秒");
            temp = 1000;
        }
        return temp;
    }


    private void sendCallbackResult(Operator operator) {
//        Log.e(TAG, "当前执行完成的步骤：" + msg);
        try {
            if (tatalStep > 1 && tatalStep != 0 && tatalStep == currentStep) {
                payTips(new Operator(0, Constant.ACTION_NAME_CCWC, "", 0, 0, 0, 0));
                reCover();
            }
            callback.OperatorAutoHandleresult(tatalStep, currentStep, operator.getName());
        } catch (Exception e) {

        }
    }

    public int getOperDuring(List<Operator> data) {
        int startIndex = -1;
        int endIndex = -1;
        int size = data.size();
        for (int i = 0; i < size; i++) {
            Operator operator = data.get(i);
            if (TextUtils.equals(operator.getName(), Constant.ACTION_NAME_CCSC)) {
                startIndex = i + 1;
            }
            if (operator.getType() == Constant.ACTION_STEP_JYT &&
                    !TextUtils.equals(operator.getName(), Constant.ACTION_NAME_YOU) && operator.getNum() > startIndex) {
                endIndex = i + 1;
            }
        }
        Log.e("qindaji", " endIndex=" + endIndex + " startIndex=" + startIndex);
        int temp = 0;
        int temp1 = 0;
        for (Operator operator : data) {
            int tempDelay = 0;
            if (operator.getType() == Constant.ACTION_STEP_JYT && (operator.getNum() >= startIndex && operator.getNum() <= endIndex)) {
                tempDelay = 1;
            } else {
                tempDelay = getHandleDelay(operator);
            }
            temp1 += operator.getDelayTime();
            temp += tempDelay;
            Log.e("qindaji", "name:" + operator.getName() + " delay=" + operator.getDelayTime()
                    + " delay1=" + tempDelay / 1000 + " temp1=" + temp1 + " temp=" + temp / 1000);
        }
        return temp;
    }

    /**
     *
     */
    private void reCover() {
        try {
            allCloseTiaoliao();
            isWorking = false;
            newDeviceControl.isChaocaiStatus(false);
            handler.sendEmptyMessageDelayed(WHAT_DELAY_LH_C, 5000);
        } catch (Exception e) {

        }
    }

    public interface OperatorAutoHandleCallback {
        void OperatorAutoHandleresult(int totalStep, int cuurrent, String msg);
    }


    /**
     * 通过流量计的默认流速值换算时长
     *
     * @param type
     * @param value
     * @return
     */
    public int mlVavluechangeMsec(String type, int value) {
        float temp = 2f;
        try {
            if (flavourSpeedDao == null) {
                flavourSpeedDao = new FlavourSpeedDao(context);
            }
            if (TextUtils.equals(type, Constant.ACTION_NAME_SHUI1)) {
                type = Constant.ACTION_NAME_SHUI;
            }
            FlavourSpeed flavourSpeed = flavourSpeedDao.queryForName(type.trim());
            Log.e(TAG, "FlavourSpeeds:" + JsonHelper.toJson(flavourSpeed));
            float speed = 25f;
            if (flavourSpeed != null && flavourSpeed.getStdData() > 0) {
                speed = flavourSpeed.getStdData();
            }
            temp = ((float) value / speed) * 1000;
            Log.e(TAG, "speed=" + speed + " type=" + type + " 初值value=" + value + " 转换后的值:" +
                    (int) temp);

        } catch (Exception e) {
            Log.e(TAG, e.getMessage());
        }
        return (int) temp;
    }

    private void allCloseTiaoliao() {
        for (int i = 1; i <= 12; i++) {
            DlcSerialPortClient.getInstance().send(Serialhelper.getInstance().getKzbSerialNo(), CmdList.OpenDO(i, 0));
        }
    }

    public int mlVavluechange(String type, int value) {
        float temp = 1f;
        try {
            if (flavourSpeedDao == null) {
                flavourSpeedDao = new FlavourSpeedDao(context);
            }
            if (TextUtils.equals(type, Constant.ACTION_NAME_SHUI1)) {
                type = Constant.ACTION_NAME_SHUI;
            }
            FlavourSpeed flavourSpeed = flavourSpeedDao.queryForName(type.trim());
            Log.e(TAG, "FlavourSpeeds:" + JsonHelper.toJson(flavourSpeed));
            float speed = 1f;
            if (flavourSpeed != null && flavourSpeed.getSpeed() > 0) {
                speed = flavourSpeed.getSpeed();
            }
            temp = (float) value * speed;
            Log.e(TAG, "name=" + type + " 初值value=" + value + " 转换后的脉冲值:" + (int) temp);
        } catch (Exception e) {
            Log.e(TAG, e.getMessage());
        }
        return (int) temp;
    }

    public void payTips(Operator operator) {
        // 1 加盖子 2拿掉盖子
        if (TextUtils.equals(operator.getName(), Constant.ACTION_NAME_JGG) && operator.getValue() == 1) {
            PlayVoiceUtil.getInstance().playRfidVoice(0);
        } else if (TextUtils.equals(operator.getName(), Constant.ACTION_NAME_JGG) && operator.getValue() == 2) {
            PlayVoiceUtil.getInstance().playRfidVoice(1);
        } else if (TextUtils.equals(operator.getName(), Constant.ACTION_NAME_JC)) {
            Log.e(TAG, "手动加菜:" + JsonHelper.toJson(operator));
            PlayVoiceUtil.getInstance().playRfidVoice(13);
        } else if (TextUtils.equals(operator.getName(), Constant.ACTION_NAME_CCWC)) {
            Log.e(TAG, "手动加菜:" + JsonHelper.toJson(operator));
            PlayVoiceUtil.getInstance().playRfidVoice(10);
        }
    }

    private String getPValue(String key) {
        String value = "-1";
        if (currentCookingMenu != null && !TextUtils.isEmpty(currentCookingMenu.getParam1())) {
            HashMap hashMap = JsonHelper.parserJson(StringEscapeUtils.unescapeJava(currentCookingMenu.getParam1()), HashMap.class);
            if (hashMap.containsKey(key)) {
                value = hashMap.get(key).toString();
            }
        }
        return value;
    }

    public List<Operator> changgeOperator(List<Operator> list, float weight, String paramer1, int cookingType) {
        Log.e(TAG, "weight:" + weight + " paramer1:" + paramer1 + " cookingType:" + cookingType);
        List<Operator> tempList = new ArrayList<>();
        HashMap<String, Object> hashMap = null;
        if (!TextUtils.isEmpty(paramer1)) {
            hashMap = JsonHelper.parserJson(StringEscapeUtils.unescapeJava(paramer1), HashMap.class);
        }
        if (actionStepItemDao == null) {
            actionStepItemDao = new ActionStepItemDao(context);
        }
        for (Operator operator : list) {
            ActionStepItem temp = actionStepItemDao.queryForAllByName(operator.getName());
            if (temp != null) {
                operator.setType(temp.getType());
            }
            if (operator.getType() == Constant.ACTION_STEP_JGT
                    || operator.getType() == Constant.ACTION_STEP_JYT) {
                double stdW = (operator.getValue1() * weight);
                operator.setValue1((int) Math.round(stdW));
                float tempvalue = mlVavluechangeMsec(operator.getName(), operator.getValue1()) / 1000f;
                operator.setDelayTime((int) Math.round(tempvalue));
                if (TextUtils.equals(operator.getName(), Constant.ACTION_NAME_YOU)) {
                    operator.setDelayTime(1);
                }
            }

            if (TextUtils.equals(operator.getName(), Constant.ACTION_NAME_CCSC)) {
                if (paramer1 != null) {
                    int value = getCcDealay(hashMap, weight, cookingType, operator.getValue1());
                    if (value == -1) {
                        value = (int) (operator.getValue() * weight);
                    }
                    operator.setValue(value);
                    Log.e(TAG, "重新计算炒菜时间:" + operator.getValue());
                    operator.setDelayTime(operator.getValue());
                }
            }
            if (TextUtils.equals(operator.getName(), Constant.ACTION_NAME_SHUI) && cookingType == 2) {
                if (paramer1 != null) {
                    //y=f*[a(x-b)+c)]+C
                    int value = getShuiValue(hashMap, weight, cookingType);
                    Log.e(TAG, "水计算量:" + value + " 公式:" + JsonHelper.toJson(hashMap));
                    if (value == -1) {
                        value = (int) (operator.getValue() * weight);
                    }
                    operator.setValue1((int) Math.ceil(value));
                    float tempvalue = mlVavluechangeMsec(operator.getName(), operator.getValue1()) / 1000f;
                    operator.setDelayTime((int) tempvalue);
                }
            }
            tempList.add(operator);
        }
        Collections.sort(tempList);
        return tempList;
    }

    private int getShuiValue(HashMap<String, Object> hashMap, float size, int cookingType) {
        float value = -1;
        if (size >= 4 && size <= 20) {
            value = getFloatMapValue(hashMap, "a1") * getCcDealay(hashMap, size, cookingType, 100)
                    + getFloatMapValue(hashMap, "f");
        } else if (size > 20) {
            value = getFloatMapValue(hashMap, "a2") * getCcDealay(hashMap, size, cookingType, 100)
                    + getFloatMapValue(hashMap, "f");
        }
        return (int) value;
    }

    public int getCcDealay(HashMap<String, Object> hashMap, float size, int cookingType) {
        double y = -1;
        try {

            if (hashMap != null && cookingType == 2) {
                // 焖 y=a(x-b)+c
                if (size <= 20) {
                    y = getIntMapValue(hashMap, "b1") * (size - getIntMapValue(hashMap, "c1")) + getIntMapValue(hashMap, "z1");
                } else {
                    y = getIntMapValue(hashMap, "b2") * (size - getIntMapValue(hashMap, "c2")) + getIntMapValue(hashMap, "z2");
                }
            } else if (hashMap != null && cookingType == 1) {
                //炒 y=am(1-5x/1000)x
                float m = (1 - 5 * size / 1000) * size;
                y = getFloatMapValue(hashMap, "a") * getFloatMapValue(hashMap, "n") * m;
                Log.e(TAG, "公式:" + JsonHelper.toJson(hashMap) + " m=" + m + " total：" + y);
            }
            Log.e(TAG, "getCcDealay y=" + y);
        } catch (Exception e) {

        }
        return (int) Math.ceil(y);
    }

    public int getCcDealay(HashMap<String, Object> hashMap, float size, int cookingType, int percent) {
        Log.e(TAG, "炒菜时长参数:" + JsonHelper.toJson(hashMap) + " size=" + size + " cookingType=" + cookingType + " percent=" + percent);
        if (percent < 1 || percent > 100) {
            return getCcDealay(hashMap, size, cookingType);
        }
        int temp = (getCcDealay(hashMap, size, cookingType) * percent) / 100;
        return temp;
    }

    private float getFloatMapValue(HashMap<String, Object> hashMap, String key) {
        float temp = -1;
        if (hashMap.containsKey(key)) {
            temp = Float.parseFloat(hashMap.get(key).toString());
            Log.e(TAG, "key=" + key + " value=" + hashMap.get(key) + "temp=" + temp);
        }
        return temp;
    }


    private int getIntMapValue(HashMap<String, Object> hashMap, String key) {
        int temp = -1;
        if (hashMap.containsKey(key)) {
            temp = Integer.parseInt(hashMap.get(key).toString());
            Log.e(TAG, "key=" + key + " value=" + hashMap.get(key) + "temp=" + temp);
        }
        return temp;
    }

    public boolean isWorking() {
        return isWorking;
    }
}
